package controller

import (
	"encoding/base64"

	"gitee.com/huangxinbo/xcas/internal/app/base"
	"gitee.com/huangxinbo/xcas/internal/constants"
	"gitee.com/huangxinbo/xcas/internal/model"
	"gitee.com/huangxinbo/xcas/internal/service"
	"gitee.com/huangxinbo/xcas/pkg/response"
	"github.com/gin-gonic/gin"
)

type UserController struct {
	base    *base.Base
	service *service.Service
}

func NewUserController(base *base.Base, service *service.Service) *UserController {

	return &UserController{
		base:    base,
		service: service,
	}
}

func (c *UserController) RegisterRoutes(router *gin.Engine) {
	userGroup := router.Group("/api/user")
	{
		userGroup.GET("", c.GetUserInfo)
		userGroup.PUT("", c.UpdateUser)
		userGroup.PUT("/password", c.UpdateUserPassword)
		userGroup.PUT("/password/set", c.SetUserPassword)
		userGroup.POST("/email/update/captcha", c.SendEmailCaptcha)
		userGroup.PUT("/email/update", c.UpdateUserEmail)
		userGroup.POST("/mobile/update/captcha", c.SendMobileCaptcha)
		userGroup.PUT("/mobile/update", c.UpdateUserMobile)
		userGroup.DELETE("", c.DeleteUser)
	}
}

// GetUserInfo Get User Info
//
//	@Summary		User Info
//	@Description	Get user info
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Success		200	{object}	model.UserResponse	"user info"
//	@Router			/api/user [get]
func (c *UserController) GetUserInfo(ctx *gin.Context) {

	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 根据用户 ID 获取用户信息（包含OAuth和密码状态）
	user, hasOAuth, err := c.service.UserService.GetUserWithOAuthInfo(ctx, userID.(string))
	if err != nil {
		response.Error[any](ctx, response.NOT_FOUND, c.base.I18n.T("User not found"), nil)
		return
	}

	// 返回用户信息（排除敏感字段）
	userInfo := model.UserResponseData{
		ID:          user.ID,
		Email:       user.Email,
		Name:        user.Name,
		FirstName:   user.FirstName,
		LastName:    user.LastName,
		VerifiedAt:  user.VerifiedAt,
		Image:       user.Image,
		Address:     user.Address,
		Region:      user.Region,
		Mobile:      user.Mobile,
		Role:        user.Role,
		CreatedAt:   user.CreatedAt,
		UpdatedAt:   user.UpdatedAt,
		HasOAuth:    hasOAuth,
		HasPassword: user.Password != nil && *user.Password != "",
	}

	response.Success(ctx, c.base.I18n.T("Success"), userInfo)
}

// UpdateUser Update User Info
//
//	@Summary		Update User
//	@Description	Update user information
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Param			request	body		model.UserUpdateRequest	true	"User update request"
//	@Success		200		{object}	model.Response			"user info updated"
//	@Router			/api/user [put]
func (c *UserController) UpdateUser(ctx *gin.Context) {
	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 绑定请求参数
	var req model.UserUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid request parameters"), nil)
		return
	}

	// 更新用户信息
	_, err := c.service.UserService.UpdateUser(ctx, userID.(string), &req)
	if err != nil {
		response.Error[any](ctx, response.ERROR, c.base.I18n.T("Failed to update user"), nil)
		return
	}

	response.Success[any](ctx, c.base.I18n.T("Success"), nil)
}

// SetUserPassword Set User Password
//
//	@Summary		Set User Password
//	@Description	Set user password (for OAuth users without password)
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Param			request	body		model.UserPasswordSetRequest	true	"Password set request"
//	@Success		200		{object}	model.Response					"password set"
//	@Router			/api/user/password/set [put]
func (c *UserController) SetUserPassword(ctx *gin.Context) {
	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 绑定请求参数
	var req model.UserPasswordSetRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid request parameters"), nil)
		return
	}

	// 解码 base64 编码的密码
	newPasswordBytes, err := base64.StdEncoding.DecodeString(req.NewPassword)
	if err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid new password format"), nil)
		return
	}
	confirmPasswordBytes, err := base64.StdEncoding.DecodeString(req.ConfirmPassword)
	if err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid confirm password format"), nil)
		return
	}

	// 更新请求中的密码为解码后的值
	req.NewPassword = string(newPasswordBytes)
	req.ConfirmPassword = string(confirmPasswordBytes)

	// 验证密码确认
	if err := req.Validate(); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("New password and confirm password do not match"), nil)
		return
	}

	// 设置用户密码
	err = c.service.UserService.SetUserPassword(ctx, userID.(string), &req)
	if err != nil {
		// 根据错误类型返回不同的错误信息
		switch err.Error() {
		case "user already has password set, please use update password endpoint":
			response.Error[any](ctx, response.USER_PASSWORD_EXISTS, c.base.I18n.T("User already has password set"), nil)
		default:
			response.Error[any](ctx, response.ERROR, c.base.I18n.T("Failed to set password"), nil)
		}
		return
	}

	response.Success[any](ctx, c.base.I18n.T("Password set successfully"), nil)
}

// SendEmailCaptcha Send Email Captcha
//
//	@Summary		Send Email Captcha
//	@Description	Send captcha to new email for email modification
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Param			request	body		model.UserEmailCaptchaRequest	true	"Email captcha request"
//	@Success		200		{object}	model.Response					"captcha sent"
//	@Router			/api/user/email/update/captcha [post]
func (c *UserController) SendEmailCaptcha(ctx *gin.Context) {
	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 绑定请求参数
	var req model.UserEmailCaptchaRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid request parameters"), nil)
		return
	}

	// 发送邮箱修改验证码
	err := c.service.UserService.SendEmailCaptcha(ctx, userID.(string), req.Email)
	if err != nil {
		// 根据错误类型返回不同的错误信息
		if err.Error() == "email already exists" {
			response.Error[any](ctx, response.USER_EMAIL_EXISTS, c.base.I18n.T("Email already exists"), nil)
		} else {
			response.Error[any](ctx, response.ERROR, c.base.I18n.T("Failed to send email captcha"), nil)
		}
		return
	}

	response.Success[any](ctx, c.base.I18n.T("Email captcha sent successfully"), nil)
}

// UpdateUserEmail Update User Email
//
//	@Summary		Update User Email
//	@Description	Update user email with captcha verification
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Param			request	body		model.UserEmailUpdateRequest	true	"Email update request"
//	@Success		200		{object}	model.Response					"email updated"
//	@Router			/api/user/email/update [put]
func (c *UserController) UpdateUserEmail(ctx *gin.Context) {
	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 绑定请求参数
	var req model.UserEmailUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid request parameters"), nil)
		return
	}

	// 更新用户邮箱
	err := c.service.UserService.UpdateUserEmail(ctx, userID.(string), &req)
	if err != nil {
		// 根据错误类型返回不同的错误信息
		switch err.Error() {
		case "invalid captcha":
			response.Error[any](ctx, response.USER_CAPTCHA_ERR, c.base.I18n.T("Invalid captcha"), nil)
		case "email already exists":
			response.Error[any](ctx, response.USER_EMAIL_EXISTS, c.base.I18n.T("Email already exists"), nil)
		default:
			response.Error[any](ctx, response.ERROR, c.base.I18n.T("Failed to update email"), nil)
		}
		return
	}

	response.Success[any](ctx, c.base.I18n.T("Email updated successfully"), nil)
}

// UpdateUserPassword Update User Password
//
//	@Summary		Update User Password
//	@Description	Update user password
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Param			request	body		model.UserPasswordUpdateRequest	true	"Password update request"
//	@Success		200		{object}	model.Response					"password updated"
//	@Router			/api/user/password [put]
func (c *UserController) UpdateUserPassword(ctx *gin.Context) {
	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 绑定请求参数
	var req model.UserPasswordUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid request parameters"), nil)
		return
	}

	// 解码 base64 编码的密码
	currentPasswordBytes, err := base64.StdEncoding.DecodeString(req.CurrentPassword)
	if err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid current password format"), nil)
		return
	}
	newPasswordBytes, err := base64.StdEncoding.DecodeString(req.NewPassword)
	if err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid new password format"), nil)
		return
	}
	confirmPasswordBytes, err := base64.StdEncoding.DecodeString(req.ConfirmPassword)
	if err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid confirm password format"), nil)
		return
	}

	// 更新请求中的密码为解码后的值
	req.CurrentPassword = string(currentPasswordBytes)
	req.NewPassword = string(newPasswordBytes)
	req.ConfirmPassword = string(confirmPasswordBytes)

	// 验证密码确认
	if err := req.Validate(); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("New password and confirm password do not match"), nil)
		return
	}

	// 更新用户密码
	err = c.service.UserService.UpdateUserPassword(ctx, userID.(string), &req)
	if err != nil {
		// 根据错误类型返回不同的错误信息
		if err.Error() == "current password is incorrect" {
			response.Error[any](ctx, response.USER_PASSWORD_ERR, c.base.I18n.T("Current password is incorrect"), nil)
		} else {
			response.Error[any](ctx, response.ERROR, c.base.I18n.T("Failed to update password"), nil)
		}
		return
	}

	response.Success[any](ctx, c.base.I18n.T("Success"), nil)
}

// SendMobileCaptcha Send Mobile Captcha
//
//	@Summary		Send Mobile Captcha
//	@Description	Send captcha to new mobile for mobile modification
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Param			request	body		model.UserMobileCaptchaRequest	true	"Mobile captcha request"
//	@Success		200		{object}	model.Response					"captcha sent"
//	@Router			/api/user/mobile/update/captcha [post]
func (c *UserController) SendMobileCaptcha(ctx *gin.Context) {
	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 绑定请求参数
	var req model.UserMobileCaptchaRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid request parameters"), nil)
		return
	}

	// 发送手机号修改验证码
	err := c.service.UserService.SendMobileCaptcha(ctx, userID.(string), req.Mobile)
	if err != nil {
		// 根据错误类型返回不同的错误信息
		if err.Error() == "mobile already exists" {
			response.Error[any](ctx, response.USER_MOBILE_EXISTS, c.base.I18n.T("Mobile already exists"), nil)
		} else {
			response.Error[any](ctx, response.ERROR, c.base.I18n.T("Failed to send mobile captcha"), nil)
		}
		return
	}

	response.Success[any](ctx, c.base.I18n.T("Mobile captcha sent successfully"), nil)
}

// UpdateUserMobile Update User Mobile
//
//	@Summary		Update User Mobile
//	@Description	Update user mobile with captcha verification
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Param			request	body		model.UserMobileUpdateRequest	true	"Mobile update request"
//	@Success		200		{object}	model.Response					"mobile updated"
//	@Router			/api/user/mobile/update [put]
func (c *UserController) UpdateUserMobile(ctx *gin.Context) {
	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 绑定请求参数
	var req model.UserMobileUpdateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid request parameters"), nil)
		return
	}

	// 更新用户手机号
	err := c.service.UserService.UpdateUserMobile(ctx, userID.(string), &req)
	if err != nil {
		// 根据错误类型返回不同的错误信息
		switch err.Error() {
		case "invalid captcha":
			response.Error[any](ctx, response.USER_CAPTCHA_ERR, c.base.I18n.T("Invalid captcha"), nil)
		case "mobile already exists":
			response.Error[any](ctx, response.USER_MOBILE_EXISTS, c.base.I18n.T("Mobile already exists"), nil)
		default:
			response.Error[any](ctx, response.ERROR, c.base.I18n.T("Failed to update mobile"), nil)
		}
		return
	}

	response.Success[any](ctx, c.base.I18n.T("Mobile updated successfully"), nil)
}

// DeleteUser Delete User
//
//	@Summary		Delete User
//	@Description	Delete user account
//	@Tags			user
//	@Accept			json
//	@Produce		json
//	@Security		BearerAuth
//	@Param			request	body		model.UserDeleteRequest	true	"User delete request"
//	@Success		200		{object}	model.Response			"user deleted"
//	@Router			/api/user [delete]
func (c *UserController) DeleteUser(ctx *gin.Context) {
	// 从 token 中获取用户 ID
	userID, exists := ctx.Get("userId")
	if !exists {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}
	if userID == "" {
		response.Error[any](ctx, response.UNAUTHORIZED, c.base.I18n.T("Invalid user ID in token"), nil)
		return
	}

	// 绑定请求参数
	var req model.UserDeleteRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid request parameters"), nil)
		return
	}

	// 删除用户
	err := c.service.UserService.DeleteUser(ctx, userID.(string), &req)
	if err != nil {
		// 根据错误类型返回不同的错误信息
		switch err.Error() {
		case "password is required for users with password":
			response.Error[any](ctx, response.USER_PASSWORD_REQUIRED, c.base.I18n.T("Password is required for users with password"), nil)
		case "password should not be provided for users without password":
			response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Password should not be provided for users without password"), nil)
		case "invalid password format":
			response.Error[any](ctx, response.INVALID_PARAMS, c.base.I18n.T("Invalid password format"), nil)
		case "password is incorrect":
			response.Error[any](ctx, response.USER_PASSWORD_ERR, c.base.I18n.T("Password is incorrect"), nil)
		case "user not found":
			response.Error[any](ctx, response.NOT_FOUND, c.base.I18n.T("User not found"), nil)
		default:
			response.Error[any](ctx, response.ERROR, c.base.I18n.T("Failed to delete user"), nil)
		}
		return
	}

	// 清除 TGC Cookie
	ctx.SetCookie(constants.TGC, "", -1, "/", "", true, true)

	// 清除访问令牌 Cookie
	ctx.SetCookie(constants.TOKEN, "", -1, "/", "", false, false)

	response.Success[any](ctx, c.base.I18n.T("User deleted successfully"), nil)
}
